#pragma once
#ifndef q3bsp_hpp
#define q3bsp_hpp

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "bsp_math.hpp"

//http://misofruit.co.kr/seojewoo/programming/opengl/Quake3Format.htm

#define LUMP_ENTITIES 0    //Game-related object descriptions.
#define LUMP_TEXTURES 1    //Surface descriptions.
#define LUMP_PLANES 2      //Planes used by map geometry.
#define LUMP_NODES 3       //BSP tree nodes.
#define LUMP_LEAFS 4       //BSP tree leaves.
#define LUMP_LEAFFACES 5   //Lists of face indices, one list per leaf.
#define LUMP_LEAFBRUSHES 6 //Lists of brush indices, one list per leaf.
#define LUMP_MODELS 7      //Descriptions of rigid world geometry in map.
#define LUMP_BRUSHES 8     //Convex polyhedra used to describe solid space.
#define LUMP_BRUSHSIDES 9  //Brush surfaces.
#define LUMP_VERTEXES 10   //Vertices used to describe faces.
#define LUMP_MESHVERTS 11  //Lists of offsets, one list per mesh.
#define LUMP_SHADERS 12    //List of special map effects.
#define LUMP_FACES 13      //Surface geometry.
#define LUMP_LIGHTMAPS 14  //Packed lightmap data.
#define LUMP_LIGHTVOLS 15  //Local illumination data.
#define LUMP_VISDATA 16    //Cluster-cluster visibility data.
#define LUMP_N 17

#define FACE_POLY 1
#define FACE_PATCH 2
#define FACE_MESH 3
#define FACE_BILL 4

struct BSPlump{
 int offset; //relativ a file kezdetehez
 int length;
};

struct BSPheader{
 char magic[4]; //IBSP
 int version; //0x2e
};

struct entities{
 char* ents;
};

/*struct BSPvertex{
 float vPos[3];           //(x,y,z)
 float vTexCoord[2];      //(u,v) texture
 float vLightmapCoord[2]; //(u,v) lightmap
 float vNormal[3];        //(x,y,z) normal vector
 char color[4];           //RGBA
};*/

class BSPvertex{
public:
 float vPos[3];           //(x,y,z)
 float vTexCoord[2];      //(u,v) texture
 float vLightmapCoord[2]; //(u,v) lightmap
 float vNormal[3];        //(x,y,z) normal vector
 char color[4];           //RGBA

 BSPvertex operator +(const BSPvertex& rhs){
  BSPvertex res;
  VECTOR_ADD(res.vPos,vPos,rhs.vPos);
  VECTOR_ADD_2D(res.vTexCoord,vTexCoord,rhs.vTexCoord);
  return res;
 }

 BSPvertex operator *(const float rhs){
  BSPvertex res;
  VECTOR_COPY(res.vPos,vPos);
  VECTOR_MUL_SCALAR(res.vPos,rhs);
  VECTOR_COPY_2D(res.vTexCoord,vTexCoord);
  VECTOR_MUL_SCALAR_2D(res.vTexCoord,rhs);
  return res;
 }

 BSPvertex& operator =(const BSPvertex& rhs){
  if(&rhs!= this){
   VECTOR_COPY(vPos,rhs.vPos);
   VECTOR_COPY_2D(vTexCoord,rhs.vTexCoord);
  }
  return *this;
 }
};

struct BSPface{
 int textureID;           //textura tomb index
 int shader;              //shader index (-1 = n/a)
 int type;                //1=polygon, 2=patch, 3=mesh, 4=billboard
 int vertIndex;           //a lap elso vertexenek indexe
 int nVerts;              //lap vertexeinek szama
 int meshVertIndex;       //az elso meshvertex indexe
 int nMeshVerts;          //meshvertexek szama
 int lightmapIndex;       //lightmap index
 int lMapCorner[2];       //a lightmap sarka
 int lMapSize[2];         //lightmap merete
 float lMapPos[3];        //lightmap origoja
 float lMapBitsets[2][3]; //s es t vektorok tere
 float vNormal[3];        //normalis
 int size[2];             //bezier dimenziok
};

struct BSPtexture{
 char texture_file[64];   //textura file neve kiterjesztes nelkul
 int flags;               //flagek
 int contents;            //tartalom
};

struct BSPlightmap{
 char imageBits[128][128][3];   //a lightmap a BSP fileban van tarolva RGB 128x128
};

struct BSPnode{
 int plane;      //sik tomb index
 int front;      //a szemben levo gyerek indexe
 int back;       //a hatul levo gyerek indexe
 int min[3];     //boundig box min
 int max[3];     //boundig box max
};

struct BSPleaf{
 int cluster;           //a lathatosagi cluster a PVS-bol
 int area;              //protal
 int min[3];            //boundig box min
 int max[3];            //boundig box max
 int leafface;          //index az elso elemre a face tombbol
 int nLeafFaces;        //lapok szama
 int leafBrush;         //index az elso elemre a brush tombbol
 int nLeafBrushes;      //brushok szama
};

struct BSPplane{
 float vNormal[3];     //sik normalisa.
 float d;              //origotl valo tavolsag
};

struct BSPvisdata{
 int nClusters;          //clusterek szama
 int bytesPerCluster;	   //byteok szama clusterenkent
 char *pBitsets;         //lathatosagi adatokat tartalmazo bytetomb
};

struct BSPbrush{
 int brushSide;           //a brush elso oldalanak indexe
 int nBrushSides;         //a brush oldalainak szama
 int textureID;           //a brush texturaja
};

struct BSPbrushside{
 int plane;              //a sik indexe
 int textureID;          //a textura indexe
};

struct BSPmodel{
 float min[3];           //bounding box min
 float max[3];           //bounding box max
 int faceIndex;          //a model elso face-jenek indexe
 int nFaces;             //lapok szama
 int brushIndex;         //az elso brush indexe
 int nBrushes;           //brushok szama
};

struct BSPshader{
 char shader_file[64]; //file neve
 int brushIndex;       //a shader brush indexe
 int unknown;          //az esetek 99%-ban 5
};

struct BSPlightvol{
 char ambient[3];       //ambient RGB
 char directional[3];	//directional RGB
 char direction[2];     //feny iranya: phi,theta
};

class q3bsp{
//private:
public:
 struct BSPheader header;
 struct BSPlump lumps[LUMP_N];

 int n_vertex;
 struct BSPvertex* vertexes;

 int n_face;
 struct BSPface* faces;

 int n_texture;
 struct BSPtexture* textures;

 int n_lightmap;
 struct BSPlightmap* lightmaps;

 int n_node;
 struct BSPnode* nodes;

 int n_leaf;
 struct BSPleaf* leafs;

 int n_leafface;
 int *leaffaces;           //leaf-ek indexe a face tomb-be

 int n_plane;
 struct BSPplane* planes;

 BSPvisdata visdata;

 int n_entity;
 char* entities;           //entitasok

 int n_brush;
 struct BSPbrush* brushes;

 int n_leafbrush;
 int *leafbrushes;        //indexek a brush tombbe

 int n_brushside;
 struct BSPbrushside* brushsides;

 int n_model;
 struct BSPmodel* models;

 int n_meshvert;
 int *meshverts;           //egy mesh vertex offsetje

 int n_shader;
 struct BSPshader* shaders;

 int n_lightvol;
 struct BSPlightvol* lightvols;

//public:
 q3bsp(){
  vertexes= NULL;
  faces= NULL;
  textures= NULL;
  lightmaps= NULL;
  nodes= NULL;
  leafs= NULL;
  leaffaces= NULL;
  planes= NULL;
  visdata.pBitsets= NULL;
  entities= NULL;
  brushes= NULL;
  leafbrushes= NULL;
  brushsides= NULL;
  models= NULL;
  meshverts= NULL;
  shaders= NULL;
  lightvols= NULL;
 }

 void destroy_bsp(){
  if(vertexes){
   //free(vertexes);
   delete[] vertexes;
  }
  if(faces){
   free(faces);
  }
  if(textures){
   free(textures);
  }
  if(lightmaps){
   free(lightmaps);
  }
  if(nodes){
   free(nodes);
  }
  if(leafs){
   free(leafs);
  }
  if(leaffaces){
   free(leaffaces);
  }
  if(planes){
   free(planes);
  }
  if(visdata.pBitsets){
   free(visdata.pBitsets);
  }
  if(entities){
   free(entities);
  }
  if(brushes){
   free(brushes);
  }
  if(leafbrushes){
   free(leafbrushes);
  }
  if(brushsides){
   free(brushsides);
  }
  if(models){
   free(models);
  }
  if(meshverts){
   free(meshverts);
  }
  if(shaders){
   free(shaders);
  }
  if(lightvols){
   free(lightvols);
  }
 }

 void print_vertexes(){
  for(int i= 0;i< n_vertex;i++){
   //printf("%f %f %f\n",vertexes[i].vPos[0],vertexes[i].vPos[1],vertexes[i].vPos[2]);
   vertexes[i].vPos[0]= -vertexes[i].vPos[0];
   float temp= vertexes[i].vPos[1];
   vertexes[i].vPos[1]= vertexes[i].vPos[2];
   vertexes[i].vPos[2]= temp;
  }
 }

 int load_bsp_file(char* bsp_filename){
  printf("OPENING BSP FILE: %s\n",bsp_filename);
  int bsp_file;
  int i;
  if((bsp_file= open(bsp_filename,O_RDONLY))== -1){
   printf("ERROR OPENING BSP FILE: %s\n",bsp_filename);
   return -1;
  }
  printf("========BSP========\n");

  if(read(bsp_file,&header,sizeof(header))!= sizeof(header)){
   printf("ERROR READING BSP FILE: header\n");
   return -1;
  }
  /*magic number*/
  /*if(read(bsp_file,&header.magic,sizeof(header.magic))!= sizeof(header.magic)){
   printf("ERROR READING BSP FILE: header\n");
   return -1;
  }*/
  printf("magic number: %c%c%c%c\n",header.magic[0],header.magic[1],header.magic[2],header.magic[3]);

  /*bsp version*/
  /*if(read(bsp_file,&header.version,sizeof(header.version))!= sizeof(header.version)){
   printf("ERROR READING BSP FILE: header\n");
   return -1;
  }*/
  printf("BSP version: %x (%d)\n",header.version,header.version);

  /*lumps*/
  printf("[Lumps]\n");
  for(i= 0;i< LUMP_N;i++){
   /*if(read(bsp_file,&lumps[i].offset,(sizeof(lumps[i].offset)))!= sizeof(lumps[i].offset)){
    printf("ERROR READING BSP FILE\n");
    return -1;
   }
   if(read(bsp_file,&lumps[i].length,(sizeof(lumps[i].length)))!= sizeof(lumps[i].length)){
    printf("ERROR READING BSP FILE\n");
    return -1;
   }*/
   if(read(bsp_file,&lumps[i],(sizeof(lumps[i])))!= sizeof(lumps[i])){
    printf("ERROR READING BSP FILE: lump info\n");
    return -1;
   }
  }

  printf("====[Entities]====\n");
  printf("[Entities]:offset: %d\n",lumps[LUMP_ENTITIES].offset);
  printf("[Entities]:length: %d\n",lumps[LUMP_ENTITIES].length);
  n_entity= lumps[LUMP_ENTITIES].length/sizeof(char);
  printf("[Entities]:num   : %d\n",n_entity);
  entities= (char*)malloc(sizeof(char)*n_entity);
  lseek(bsp_file,lumps[LUMP_ENTITIES].offset,SEEK_SET);
  if(read(bsp_file,entities,lumps[LUMP_ENTITIES].length)!= lumps[LUMP_ENTITIES].length){
   printf("ERROR READING BSP FILE: entities\n");
   return -1;
  }
  printf("====[Entities END]====\n");

  printf("====[Textures]====\n");
  printf("[Textures]:offset: %d\n",lumps[LUMP_TEXTURES].offset);
  printf("[Textures]:length: %d\n",lumps[LUMP_TEXTURES].length);
  n_texture= lumps[LUMP_TEXTURES].length/sizeof(struct BSPtexture);
  printf("[Textures]:num   : %d\n",n_texture);
  textures= (struct BSPtexture*)malloc(sizeof(struct BSPtexture)*n_texture);
  lseek(bsp_file,lumps[LUMP_TEXTURES].offset,SEEK_SET);
  if(read(bsp_file,textures,lumps[LUMP_TEXTURES].length)!= lumps[LUMP_TEXTURES].length){
   printf("ERROR READING BSP FILE: textures\n");
   return -1;
  }
  printf("[Textures]:list:\n");
  for(i= 0;i< n_texture;i++){
   printf("%s\n",textures[i].texture_file);
  }
  printf("====[Textures END]====\n");

  printf("====[Planes]====\n");
  printf("[Planes]:offset: %d\n",lumps[LUMP_PLANES].offset);
  printf("[Planes]:length: %d\n",lumps[LUMP_PLANES].length);
  n_plane= lumps[LUMP_PLANES].length/sizeof(struct BSPplane);
  printf("[Planes]:num   : %d\n",n_plane);
  planes= (struct BSPplane*)malloc(sizeof(struct BSPplane)*n_plane);
  lseek(bsp_file,lumps[LUMP_PLANES].offset,SEEK_SET);
  if(read(bsp_file,planes,lumps[LUMP_PLANES].length)!= lumps[LUMP_PLANES].length){
   printf("ERROR READING BSP FILE: planes\n");
   return -1;
  }
  printf("====[Planes END]====\n");

  printf("====[Nodes]====\n");
  printf("[Nodes]:offset: %d\n",lumps[LUMP_NODES].offset);
  printf("[Nodes]:length: %d\n",lumps[LUMP_NODES].length);
  n_node= lumps[LUMP_NODES].length/sizeof(struct BSPnode);
  printf("[Nodes]:num   : %d\n",n_node);
  nodes= (struct BSPnode*)malloc(sizeof(struct BSPnode)*n_node);
  lseek(bsp_file,lumps[LUMP_NODES].offset,SEEK_SET);
  if(read(bsp_file,nodes,lumps[LUMP_NODES].length)!= lumps[LUMP_NODES].length){
   printf("ERROR READING BSP FILE: nodes\n");
   return -1;
  }
  printf("====[Nodes END]====\n");

  printf("====[Leafs]====\n");
  printf("[Leafs]:offset: %d\n",lumps[LUMP_LEAFS].offset);
  printf("[Leafs]:length: %d\n",lumps[LUMP_LEAFS].length);
  n_leaf= lumps[LUMP_LEAFS].length/sizeof(struct BSPleaf);
  printf("[Leafs]:num   : %d\n",n_leaf);
  leafs= (struct BSPleaf*)malloc(sizeof(struct BSPleaf)*n_leaf);
  lseek(bsp_file,lumps[LUMP_LEAFS].offset,SEEK_SET);
  if(read(bsp_file,leafs,lumps[LUMP_LEAFS].length)!= lumps[LUMP_LEAFS].length){
   printf("ERROR READING BSP FILE: leafs\n");
   return -1;
  }
  printf("====[Leafs END]====\n");

  printf("====[Leaf faces]====\n");
  printf("[Leaf faces]:offset: %d\n",lumps[LUMP_LEAFFACES].offset);
  printf("[Leaf faces]:length: %d\n",lumps[LUMP_LEAFFACES].length);
  n_leafface= lumps[LUMP_LEAFFACES].length/sizeof(leaffaces);
  printf("[Leaf faces]:num   : %d\n",n_leafface);
  leaffaces= (int*)malloc(sizeof(int)*n_leafface);
  lseek(bsp_file,lumps[LUMP_LEAFFACES].offset,SEEK_SET);
  if(read(bsp_file,leaffaces,lumps[LUMP_LEAFFACES].length)!= lumps[LUMP_LEAFFACES].length){
   printf("ERROR READING BSP FILE: leaffaces\n");
   return -1;
  }
  printf("====[Leaf faces END]====\n");

  printf("====[Leaf brushes]====\n");
  printf("[Leaf brushes]:offset: %d\n",lumps[LUMP_LEAFBRUSHES].offset);
  printf("[Leaf brushes]:length: %d\n",lumps[LUMP_LEAFBRUSHES].length);
  n_leafbrush= lumps[LUMP_LEAFBRUSHES].length/sizeof(int);
  printf("[Leaf brushes]:num   : %d\n",n_leafbrush);
  leafbrushes= (int*)malloc(sizeof(int)*n_leafbrush);
  lseek(bsp_file,lumps[LUMP_LEAFBRUSHES].offset,SEEK_SET);
  if(read(bsp_file,leafbrushes,lumps[LUMP_LEAFBRUSHES].length)!= lumps[LUMP_LEAFBRUSHES].length){
   printf("ERROR READING BSP FILE: leafbrushes\n");
   return -1;
  }
  printf("====[Leaf brushes END]====\n");

  printf("====[Models]====\n");
  printf("[Models]:offset: %d\n",lumps[LUMP_MODELS].offset);
  printf("[Models]:length: %d\n",lumps[LUMP_MODELS].length);
  n_model= lumps[LUMP_MODELS].length/sizeof(struct BSPmodel);
  printf("[Models]:num   : %d\n",n_model);
  models= (struct BSPmodel*)malloc(sizeof(struct BSPmodel)*n_model);
  lseek(bsp_file,lumps[LUMP_MODELS].offset,SEEK_SET);
  if(read(bsp_file,models,lumps[LUMP_MODELS].length)!= lumps[LUMP_MODELS].length){
   printf("ERROR READING BSP FILE: models\n");
   return -1;
  }
  printf("====[Models END]====\n");

  printf("====[Brushes]====\n");
  printf("[Brushes]:offset: %d\n",lumps[LUMP_BRUSHES].offset);
  printf("[Brushes]:length: %d\n",lumps[LUMP_BRUSHES].length);
  n_brush= lumps[LUMP_BRUSHES].length/sizeof(struct BSPbrush);
  printf("[Brushes]:num   : %d\n",n_brush);
  brushes= (struct BSPbrush*)malloc(sizeof(struct BSPbrush)*n_brush);
  lseek(bsp_file,lumps[LUMP_BRUSHES].offset,SEEK_SET);
  if(read(bsp_file,brushes,lumps[LUMP_BRUSHES].length)!= lumps[LUMP_BRUSHES].length){
   printf("ERROR READING BSP FILE: brushes\n");
   return -1;
  }
  printf("====[Brushes END]====\n");

  printf("====[Brush sides]====\n");
  printf("[Brush sides]:offset: %d\n",lumps[LUMP_BRUSHSIDES].offset);
  printf("[Brush sides]:length: %d\n",lumps[LUMP_BRUSHSIDES].length);
  n_brushside= lumps[LUMP_BRUSHSIDES].length/sizeof(struct BSPbrushside);
  printf("[Brush sides]:num   : %d\n",n_brushside);
  brushsides= (struct BSPbrushside*)malloc(sizeof(struct BSPbrushside)*n_brushside);
  lseek(bsp_file,lumps[LUMP_BRUSHSIDES].offset,SEEK_SET);
  if(read(bsp_file,brushsides,lumps[LUMP_BRUSHSIDES].length)!= lumps[LUMP_BRUSHSIDES].length){
   printf("ERROR READING BSP FILE: brushsides\n");
   return -1;
  }
  printf("====[Brush sides END]====\n");

  printf("====[Vertexes]====\n");
  printf("[Vertexes]:offset: %d\n",lumps[LUMP_VERTEXES].offset);
  printf("[Vertexes]:length: %d\n",lumps[LUMP_VERTEXES].length);
  n_vertex= lumps[LUMP_VERTEXES].length/sizeof(struct BSPvertex);
  printf("[Vertexes]:num   : %d\n",n_vertex);
  //vertexes= (struct BSPvertex*)malloc(sizeof(struct BSPvertex)*n_vertex);
  vertexes= new BSPvertex[n_vertex];
  lseek(bsp_file,lumps[LUMP_VERTEXES].offset,SEEK_SET);
  if(read(bsp_file,vertexes,lumps[LUMP_VERTEXES].length)!= lumps[LUMP_VERTEXES].length){
   printf("ERROR READING BSP FILE: vertexes\n");
   return -1;
  }
  printf("====[Vertexes END]====\n");

  printf("====[Mesh vertexes]====\n");
  printf("[Mesh vertexes]:offset: %d\n",lumps[LUMP_MESHVERTS].offset);
  printf("[Mesh vertexes]:length: %d\n",lumps[LUMP_MESHVERTS].length);
  n_meshvert= lumps[LUMP_MESHVERTS].length/sizeof(int);
  printf("[Mesh vertexes]:num   : %d\n",n_meshvert);
  meshverts= (int*)malloc(sizeof(int)*n_meshvert);
  lseek(bsp_file,lumps[LUMP_MESHVERTS].offset,SEEK_SET);
  if(read(bsp_file,meshverts,lumps[LUMP_MESHVERTS].length)!= lumps[LUMP_MESHVERTS].length){
   printf("ERROR READING BSP FILE: meshverts\n");
   return -1;
  }
  printf("====[Mesh vertexes END]====\n");

  printf("====[Shaders]====\n");
  printf("[Shaders]:offset: %d\n",lumps[LUMP_SHADERS].offset);
  printf("[Shaders]:length: %d\n",lumps[LUMP_SHADERS].length);
  n_shader= lumps[LUMP_SHADERS].length/sizeof(struct BSPshader);
  printf("[Shaders]:num   : %d\n",n_shader);
  shaders= (struct BSPshader*)malloc(sizeof(struct BSPshader)*n_shader);
  lseek(bsp_file,lumps[LUMP_SHADERS].offset,SEEK_SET);
  if(read(bsp_file,shaders,lumps[LUMP_SHADERS].length)!= lumps[LUMP_SHADERS].length){
   printf("ERROR READING BSP FILE: shaders\n");
   return -1;
  }
  printf("[Shaders]:list:\n");
  for(i= 0;i< n_shader;i++){
   printf("%s\n",shaders[i].shader_file);
  }
  printf("====[Shaders END]====\n");

  printf("====[Faces]====\n");
  printf("[Faces]:offset: %d\n",lumps[LUMP_FACES].offset);
  printf("[Faces]:length: %d\n",lumps[LUMP_FACES].length);
  n_face= lumps[LUMP_FACES].length/sizeof(struct BSPface);
  printf("[Faces]:num   : %d\n",n_face);
  faces= (struct BSPface*)malloc(sizeof(struct BSPface)*n_face);
  lseek(bsp_file,lumps[LUMP_FACES].offset,SEEK_SET);
  if(read(bsp_file,faces,lumps[LUMP_FACES].length)!= lumps[LUMP_FACES].length){
   printf("ERROR READING BSP FILE: faces\n");
   return -1;
  }
  printf("====[Faces END]====\n");

  printf("====[Lightmaps]====\n");
  printf("[Lightmaps]:offset: %d\n",lumps[LUMP_LIGHTMAPS].offset);
  printf("[Lightmaps]:length: %d\n",lumps[LUMP_LIGHTMAPS].length);
  n_lightmap= lumps[LUMP_LIGHTMAPS].length/sizeof(struct BSPlightmap);
  printf("[Lightmaps]:num   : %d\n",n_lightmap);
  lightmaps= (struct BSPlightmap*)malloc(sizeof(struct BSPlightmap)*n_lightmap);
  lseek(bsp_file,lumps[LUMP_LIGHTMAPS].offset,SEEK_SET);
  if(read(bsp_file,lightmaps,lumps[LUMP_LIGHTMAPS].length)!= lumps[LUMP_LIGHTMAPS].length){
   printf("ERROR READING BSP FILE: lightmaps\n");
   return -1;
  }
  printf("====[Lightmaps END]====\n");

  printf("====[Lightvols]====\n");
  printf("[Lightvols]:offset: %d\n",lumps[LUMP_LIGHTVOLS].offset);
  printf("[Lightvols]:length: %d\n",lumps[LUMP_LIGHTVOLS].length);
  n_lightvol= lumps[LUMP_LIGHTVOLS].length/sizeof(struct BSPlightvol);
  printf("[Lightvols]:num   : %d\n",n_lightvol);
  lightvols= (struct BSPlightvol*)malloc(sizeof(struct BSPlightvol)*n_lightvol);
  lseek(bsp_file,lumps[LUMP_LIGHTVOLS].offset,SEEK_SET);
  if(read(bsp_file,lightvols,lumps[LUMP_LIGHTVOLS].length)!= lumps[LUMP_LIGHTVOLS].length){
   printf("ERROR READING BSP FILE: lightvols\n");
   return -1;
  }
  printf("====[Lightvols END]====\n");

  printf("====[Visibility data]====\n");
  printf("[Visibility data]:offset: %d\n",lumps[LUMP_VISDATA].offset);
  printf("[Visibility data]:length: %d\n",lumps[LUMP_VISDATA].length);
  visdata.pBitsets= (char*)malloc(lumps[LUMP_VISDATA].length-(sizeof(int)*2));
  lseek(bsp_file,lumps[LUMP_VISDATA].offset,SEEK_SET);
  if(read(bsp_file,&visdata.nClusters,sizeof(visdata.nClusters))!= sizeof(visdata.nClusters)){
   printf("ERROR READING BSP FILE: visdata\n");
   return -1;
  }
  if(read(bsp_file,&visdata.bytesPerCluster,sizeof(visdata.bytesPerCluster))!= sizeof(visdata.bytesPerCluster)){
   printf("ERROR READING BSP FILE: visdata\n");
   return -1;
  }
  if(read(bsp_file,visdata.pBitsets,sizeof(lumps[LUMP_VISDATA].length-(sizeof(int)*2)))!= sizeof(lumps[LUMP_VISDATA].length-(sizeof(int)*2))){
   printf("ERROR READING BSP FILE: visdata\n");
   return -1;
  }
  printf("[Visibility data]:number of clusters: %d\n",visdata.nClusters);
  printf("[Visibility data]:bytes/cluster     : %d\n",visdata.bytesPerCluster);
  printf("====[Visibility data END]====\n");


  printf("========BSP========\n");
  close(bsp_file);
  printf("CLOSED BSP FILE: %s\n",bsp_filename);
  return 0;
 }
};

#endif
